using System;
using System.Collections.Generic;
using System.Text;

using SlimDX;
using SlimDX.Direct3D9;
using System.Collections;

using miciv;
using miciv.Rendering;
using miciv.Geometry;
using micivCore.Components;

namespace micivCore.Data
{
    public class MapTile
    {
        protected MapTileDefinition m_definition;
        public MapTileDefinition Definition
        {
            get
            {
                return this.m_definition;
            }
            set
            {
                if (value != this.m_definition)
                {
                    this.m_definition = value;
                }
            }
        }

        protected Vector2 m_f2Position;
        public Vector2 Position
        {
            get
            {
                return this.m_f2Position;
            }
            set
            {
                if (value != this.m_f2Position)
                {
                    this.m_f2Position = value;
                    foreach (DictionaryEntry de in this.m_htblRenderables)
                    {
                        (de.Value as MapTileRenderable).Position = value;
                    }
                }
            }
        }

        protected Vector2 m_f2Size;
        public Vector2 Size
        {
            get
            {
                return this.m_f2Size;
            }
            set
            {
                if (value != this.m_f2Size)
                {
                    this.m_f2Size = value;
                    foreach (DictionaryEntry de in this.m_htblRenderables)
                    {
                        (de.Value as MapTileRenderable).Size = value;
                    }
                }
            }
        }

        protected CoMapProto m_coMapProto;
        public CoMapProto MapProto
        {
            get
            {
                return this.m_coMapProto;
            }
        }

        protected List<IRendererContext> m_lstRestrictedRendererContexts;
        virtual public List<IRendererContext> RestrictedRendererContexts
        {
            get
            {
                return this.m_lstRestrictedRendererContexts;
            }
            set
            {
                this.m_lstRestrictedRendererContexts = value;
                foreach (DictionaryEntry de in this.m_htblRenderables)
                {
                    (de.Value as MapTileRenderable).RestrictedRendererContexts = value;
                }
            }
        }

        protected List<IUnit> m_lstUnits;
        public List<IUnit> Units
        {
            get
            {
                return this.m_lstUnits;
            }
        }

        protected IMapCommunicator m_mapCommunicator;
        public IMapCommunicator MapCommunicator
        {
            get
            {
                return this.m_mapCommunicator;
            }
            set
            {
                this.m_mapCommunicator = value;
            }
        }

        protected MapCoords m_mapCoords;
        public MapCoords Coords
        {
            get
            {
                return this.m_mapCoords;
            }
            set
            {
                this.m_mapCoords = value;
            }
        }

        protected Hashtable m_htblRenderables;

        public MapTile(MapTileDefinition _definition, CoMapProto _coMapProto)
        {
            this.Definition = _definition;
            this.m_coMapProto = _coMapProto;
            this.m_lstUnits = new List<IUnit>();
            this.m_htblRenderables = new  Hashtable(this.Definition.GeometryDefinitions.Count);
            foreach (DictionaryEntry de in this.Definition.GeometryDefinitions)
            {
                MapTileGeometryDefinition geometryDefinition = de.Value as MapTileGeometryDefinition;
                MapTileRenderable renderable = new MapTileRenderable(this, geometryDefinition);
                this.m_htblRenderables.Add(geometryDefinition.ID, renderable);
            }
            // set default geometry visible
            (this.m_htblRenderables[_definition.DefaultGeometry] as MapTileRenderable).IsVisible = true;
        }


        public void Update(float _deltaTime)
        {
            foreach (DictionaryEntry de in this.m_htblRenderables)
            {
                MapTileRenderable renderable = de.Value as MapTileRenderable;
                if (false != renderable.IsVisible)
                {
                    renderable.UpdateData(_deltaTime);
                    renderable.Renderer.Add(renderable);
                }
            }
        }

        public void Release()
        {
            foreach (DictionaryEntry de in this.m_htblRenderables)
            {
                (de.Value as MapTileRenderable).Release();
            }
            this.m_htblRenderables.Clear();
        }

        public void SetVisible(string _strRenderable, bool _bState)
        {
            if (false != this.m_htblRenderables.ContainsKey(_strRenderable))
            {
                (this.m_htblRenderables[_strRenderable] as MapTileRenderable).IsVisible = _bState;
            }
        }

        public void AttachUnit(IUnit _unit)
        {
            if (false == this.m_lstUnits.Contains(_unit))
            {
                this.m_lstUnits.Add(_unit);
                if ((null != _unit.MapTile) && (this != _unit.MapTile))
                {
                    MapTile mapTile = _unit.MapTile;
                    mapTile.DetachUnit(_unit);
                }
                _unit.MapTile = this;
            }
        }

        public void DetachUnit(IUnit _unit)
        {
            if (false != this.m_lstUnits.Contains(_unit))
            {
                this.m_lstUnits.Remove(_unit);
                if (this == _unit.MapTile)
                {
                    _unit.MapTile = null;
                }
            }
        }

        public float GetSpeed(string _strType)
        {
            if (false != this.Definition.Layers.ContainsKey(_strType))
            {
                MapTileLayer layer = this.Definition.Layers[_strType] as MapTileLayer;
                if (false != layer.HasModifier("speed"))
                {
                    return (float)layer.GetModifier("speed");
                }
            }
            return 0.0f;
        }

        public void GetNeighbors(ref List<MapTile> _lstNeighbors)
        {
            this.MapCommunicator.GetNeighbors(this.Coords, ref _lstNeighbors);
        }
    }
}
